import {
  Directive,
  ElementRef,
  OnInit,
  AfterViewInit,
  NgZone,
  AfterContentInit,
  OnDestroy,
  HostListener,
  Renderer2,
  OnChanges,
  Input,
  SimpleChanges,
  ViewChild,
  ChangeDetectorRef,
  Output,
  EventEmitter,
} from "@angular/core";
import { Subject, Subscription, Observable } from "rxjs";
import { debounceTime } from "rxjs/operators";
declare var graphChart: any;
declare var d3: any;

@Directive({
  selector: "[appNetworkGraph]",
})
export class NetworkGraphDirective
  implements OnInit, OnChanges, AfterViewInit, AfterContentInit, OnDestroy {
  @Input() miserables: any;
  @Input() histroyNode: any;
  @Output() emmitEvent: EventEmitter<any> = new EventEmitter<any>();
  resizeSub: Subject<any> = new Subject();
  resizeSub$: Subscription;
  visWidth: number;
  visHeight: number;
  simulation: any;
  graphIns: any;
  @ViewChild("svg", { static: true }) svgEl: ElementRef;
  @HostListener("window:resize")
  _resize() {
    this.resizeSub.next();
  }
  constructor(
    private ele: ElementRef,
    private zone: NgZone,
    private render: Renderer2,
    private cdr: ChangeDetectorRef
  ) {}
  ngOnInit(): void {
    console.log("ngOnInit");
    this.resizeSub$ = this.resizeSub
      .asObservable()
      .pipe(debounceTime(300))
      .subscribe(() => {
        this.windowResize();
      });
  }
  ngAfterViewInit(): void {
    this.resizeSub.next();
  }
  ngAfterContentInit(): void {
    console.log("ngAfterContentInit");
  }
  ngOnChanges(changes: SimpleChanges): void {
    const { miserables, histroyNode } = changes;
    console.log("ngOnChanges");
    if (miserables && miserables.currentValue) {
      this.zone.runOutsideAngular(() => {
        this.renderGraph();
      });
    }
    if (histroyNode && histroyNode.currentValue) {
      const { nodes, links } = histroyNode.currentValue.data;
      this.graphIns.update({
        nodes,
        links,
      });
    }
  }
  ngOnDestroy(): void {
    console.log("ngOnDestroy");
    if (this.resizeSub$) {
      this.resizeSub$.unsubscribe();
      this.resizeSub$ = null;
    }
  }

  private windowResize() {
    const el: HTMLElement = this.ele.nativeElement;
    this.visWidth = el.offsetWidth;
    this.visHeight = el.offsetHeight;
  }
  initalizeNetwork() {
    const { visWidth, visHeight } = this;
  }
  renderGraph() {
    const { simulation, miserables, visWidth, visHeight } = this;
    const dispatch = d3.dispatch("nodeClick");
    this.graphIns = graphChart()
      .width(visWidth)
      .height(visHeight > 500 ? visHeight : 500)
      .fillNode("#758686")
      .strokeNode("#494853")
      .fillNodeHover("#9d3a43")
      .fillNeighbors("#b38a38")
      .fillText("#fff")
      .strokeLinkHover(d3.rgb(250, 250, 250, 1))
      .dispatch(dispatch)
      .miserables(miserables);
    dispatch.on("nodeClick", (data) => {
      this.emmitEvent.emit({ type: "nodeClick", data });
    });
    const graphData = {
      nodes: miserables.nodes,
      edges: miserables.edges,
    };
    this.emmitEvent.emit({
      type: "nodeClick",
      data: { nodes: miserables.nodes, links: miserables.edges },
    });
    this.graphIns.update({ nodes: miserables.nodes, links: miserables.edges });
    // this.draw(graphData, graph);
  }
}
